/**
 * 
 */
package gmu.drr.entity;

import gmu.drr.entity.netFactory.ModelFactory;

import java.util.ArrayList;
import java.util.Properties;

import cern.jet.random.AbstractContinousDistribution;
import cern.jet.random.engine.*;

/** 
 * The overall model has responsibility for network-scale replicates - variations on the core network construction or contents.
 * Replicates of a particular network are the responsibility of the simulation run classes.
 * @author RothmD01
 * @see gmu.drr.entity.netSim.NetworkSimRun
 */
public abstract class ModelModel {
	private static final ModelModel inst = null;

	/**
	 * SUBCLASS MUST OVERRIDE
	 * instances of model are intended to be singletons...
	 * @return the inst
	 */
	public static ModelModel getInst() {
		// no default implementation
		// SUBCLASS MUST OVERRIDE
		return inst;	
	}

	private RandomEngine randNum;
	/**
	 * @return the randNum
	 */
	public RandomEngine getRandNum() {
		return randNum;
	}

	/**
	 * @param randNum the randNum to set
	 */
	public void setRandNum(RandomEngine randNum) {
		this.randNum = randNum;
	}

	/**
	 * @return the randSeed
	 */
	public int getRandSeed() {
		return randSeed;
	}

	/**
	 * @param randSeed the randSeed to set
	 */
	public void setRandSeed(int randSeed) {
		this.randSeed = randSeed;
	}

	private int randSeed = (new RandomSeedGenerator() ).nextSeed();

	/**
	 * @uml.property  name="spec_UserGroupRelModel"
	 */
	private Properties spec_UserGroupRelModel;

	/**
	 * Getter of the property <tt>spec_UserGroupRelModel</tt>
	 * @return  Returns the spec_UserGroupRelModel.
	 * @uml.property  name="spec_UserGroupRelModel"
	 */
	public Properties getSpec_UserGroupRelModel() {
		return spec_UserGroupRelModel;
	}

	/**
	 * Setter of the property <tt>spec_UserGroupRelModel</tt>
	 * @param spec_UserGroupRelModel  The spec_UserGroupRelModel to set.
	 * @uml.property  name="spec_UserGroupRelModel"
	 */
	public void setSpec_UserGroupRelModel(Properties spec_UserGroupRelModel) {
		this.spec_UserGroupRelModel = spec_UserGroupRelModel;
	}

	/**
	 * @uml.property  name="spec_ProdRelModel"
	 */
	private Properties spec_ProdRelModel;

	/**
	 * Getter of the property <tt>spec_ProdRelModel</tt>
	 * @return  Returns the spec_ProdRelModel.
	 * @uml.property  name="spec_ProdRelModel"
	 */
	public Properties getSpec_ProdRelModel() {
		return spec_ProdRelModel;
	}

	/**
	 * Setter of the property <tt>spec_ProdRelModel</tt>
	 * @param spec_ProdRelModel  The spec_ProdRelModel to set.
	 * @uml.property  name="spec_ProdRelModel"
	 */
	public void setSpec_ProdRelModel(Properties spec_ProdRelModel) {
		this.spec_ProdRelModel = spec_ProdRelModel;
	}

	/**
	 * @uml.property  name="spec_DocGroupRelModel"
	 */
	private String spec_DocGroupRelModel = "";

	/**
	 * Getter of the property <tt>spec_DocGroupRelModel</tt>
	 * @return  Returns the spec_DocGroupRelModel.
	 * @uml.property  name="spec_DocGroupRelModel"
	 */
	public String getSpec_DocGroupRelModel() {
		return spec_DocGroupRelModel;
	}

	/**
	 * Setter of the property <tt>spec_DocGroupRelModel</tt>
	 * @param spec_DocGroupRelModel  The spec_DocGroupRelModel to set.
	 * @uml.property  name="spec_DocGroupRelModel"
	 */
	public void setSpec_DocGroupRelModel(String spec_DocGroupRelModel) {
		this.spec_DocGroupRelModel = spec_DocGroupRelModel;
	}

	/**
	 * @uml.property  name="Ku"
	 */
	private int ku;

	/**
	 * Getter of the property <tt>Ku</tt>
	 * @return  Returns the ku.
	 * @uml.property  name="Ku"
	 */
	public int getKu() {
		return ku;
	}

	/**
	 * Setter of the property <tt>Ku</tt>
	 * @param Ku  The ku to set.
	 * @uml.property  name="Ku"
	 */
	public void setKu(int ku) {
		UserGroup.setKu(ku);
		this.ku = ku;
	}

	/**
	 * @uml.property  name="Kd"
	 */
	private int kd;

	/**
	 * Getter of the property <tt>Kd</tt>
	 * @return  Returns the kd.
	 * @uml.property  name="Kd"
	 */
	public int getKd() {
		return kd;
	}

	/**
	 * Setter of the property <tt>Kd</tt>
	 * @param Kd  The kd to set.
	 * @uml.property  name="Kd"
	 */
	public void setKd(int kd) {
		DocGroup.setKd(kd);
		this.kd = kd;
	}

	/**
	 * @uml.property  name="spec_NetEdgeWeightModel"
	 */
	private Properties spec_NetEdgeWeightModel;

	/**
	 * Getter of the property <tt>spec_NetEdgeWeightModel</tt>
	 * @return  Returns the spec_NetEdgeWeightModel.
	 * @uml.property  name="spec_NetEdgeWeightModel"
	 */
	public Properties getSpec_NetEdgeWeightModel() {
		return spec_NetEdgeWeightModel;
	}

	/**
	 * Setter of the property <tt>spec_NetEdgeWeightModel</tt>
	 * @param spec_NetEdgeWeightModel  The spec_NetEdgeWeightModel to set.
	 * @uml.property  name="spec_NetEdgeWeightModel"
	 */
	public void setSpec_NetEdgeWeightModel(Properties spec_NetEdgeWeightModel) {
		this.spec_NetEdgeWeightModel = spec_NetEdgeWeightModel;
	}

	/**
	 * @uml.property  name="NetNodeActModel"
	 */
	private Properties netNodeActModel;

	/**
	 * Getter of the property <tt>NetNodeActModel</tt>
	 * @return  Returns the netNodeActModel.
	 * @uml.property  name="NetNodeActModel"
	 */
	public Properties getNetNodeActModel() {
		return netNodeActModel;
	}

	/**
	 * Setter of the property <tt>NetNodeActModel</tt>
	 * @param NetNodeActModel  The netNodeActModel to set.
	 * @uml.property  name="NetNodeActModel"
	 */
	public void setNetNodeActModel(Properties netNodeActModel) {
		this.netNodeActModel = netNodeActModel;
	}
	
	private ArrayList<User> userList;
	/**
	 * @return the userList
	 */
	public ArrayList<User> getUserList() {
		return userList;
	}

	/**
	 * @param userList the userList to set
	 */
	public void setUserList(ArrayList<User> userList) {
		this.userList = userList;
	}

	/**
	 * @return the docList
	 */
	public ArrayList<Doc> getDocList() {
		return docList;
	}

	/**
	 * @param docList the docList to set
	 */
	public void setDocList(ArrayList<Doc> docList) {
		this.docList = docList;
	}

	/**
	 * @return the edgeList
	 */
	public ArrayList<NetEdge> getEdgeList() {
		return edgeList;
	}

	/**
	 * @param edgeList the edgeList to set
	 */
	public void setEdgeList(ArrayList<NetEdge> edgeList) {
		this.edgeList = edgeList;
	}

	/**
	 * @return the factory
	 */
	public ModelFactory getFactory() {
		return factory;
	}

	/**
	 * @param factory the factory to set
	 */
	public void setFactory(ModelFactory factory) {
		this.factory = factory;
	}

	private ArrayList<Doc> docList;
	/**
	 * tracking a list of edges - trying to gather them through the userlist may be very challenging...
	 */
	private ArrayList<NetEdge> edgeList; 
	/**
	 * the constructor factory - needed for initialization, does it need to be tracked longer term?
	 * note also that it's a pointer to the generic, rather than to a specific implementation.  may want to
	 * be overridden (check how this works for inherited methods...)
	 */
	private ModelFactory factory;
	

	/**
	 * 
	 */
	protected AbstractContinousDistribution userDegreeDist;

	/**
	 * @return the userDegreeDist
	 */
	public AbstractContinousDistribution getUserDegreeDist() {
		return userDegreeDist;
	}

	/**
	 * @param userDegreeDist the userDegreeDist to set
	 */
	public void setUserDegreeDist(AbstractContinousDistribution userDegreeDist) {
		this.userDegreeDist = userDegreeDist;
	}

	protected ModelModel() {
		// only visible to subclasses
	}
}
